<?php

declare(strict_types=1);

namespace App\Api\Service;

use App\Model\Car;
use App\Model\CarCategory;
use Hyperf\Collection\Arr;
use Hyperf\Collection\Collection;
use Hyperf\Contract\LengthAwarePaginatorInterface;
use Hyperf\Database\Model\Builder;

class CarService
{
    /**
     * 车辆列表
     * @return LengthAwarePaginatorInterface
     */
    public function index(): LengthAwarePaginatorInterface
    {
        // 参数
        $request = request();
        $day = (int)$request->input('day');
        $categoryId = (int)$request->input('category_id', 0);
        $volumeDirection = (string)$request->input('volume_direction', 'desc');
        $configs = array_filter((array)$request->input('configs', []));
        $priceDirection = (string)$request->input('price_direction', 'desc');
        $is_hot = (string)$request->input('is_hot', '0');
        $start_time = (string)$request->input('start_time', '');
        $end_time = (string)$request->input('end_time', '');
        // 查询
        $res = Car::query()
            ->where('status', 1)
            ->when(($is_hot == 1), function(Builder $builder, $item) {
                $builder->where('is_hot', '1');
            })
            ->when(!empty($categoryId), function (Builder $builder) use ($categoryId) {
                $builder->whereJsonContains('car_category_ids', $categoryId);
            })
            ->when(!empty($configs), function (Builder $builder) use ($configs) {
                $builder->where(function (Builder $builder) use ($configs) {
                    foreach ($configs as $config) {
                        $builder->orWhereJsonContains('base_config', ['value' => $config]);
                    }
                });
            })
            ->orderBy('volume', $volumeDirection)
            ->orderBy('price', $priceDirection)
            ->latest('id')
            ->paginate();

        // 分类查询
        $categoryIds = Arr::flatten($res->pluck('car_category_ids')->toArray());
        $categories = new Collection();
        if (!empty($categoryIds)) {
            $categories = CarCategory::query()
                ->whereIn('id', array_unique($categoryIds))
                ->pluck('icon', 'id')
                ->filter();
        }

        // 组装数据
        /** @var Car $model */
        foreach ($res as $model) {
            $model_arr = $model->toArray();
            $model->icon = $this->getCategoryIcon($model, $categories);
            $price = $this->getCarPrice($model_arr);
            $model->price = $price;
            $model->average_price = $price;
            $subtotal = $day * $price;
            if(!empty($start_time) && !empty($end_time)){
                $model->price_calendar = $this->getCarPriceCalendar($model_arr, strtotime($start_time), strtotime($end_time));
                $subtotal = "0";
                foreach ($model->price_calendar as $k => $v){
                    $subtotal = bcadd($subtotal, (string)$v);
                }
                $model->average_price = bcdiv($subtotal, (string)count($model->price_calendar), 0);
            }
            $model->total_price = $subtotal;
            $model->setVisible(['id', 'cover', 'name', 'icon', 'describe', 'total_price', 'price', 'average_price', 'price_calendar']);
        }

        return $res;
    }

    /**
     * 车辆详情
     * @param mixed $id
     * @return Car
     */
    public function show(mixed $id): Car
    {
        $request = request();
        $start_time = (string)$request->input('start_time', '');
        $end_time = (string)$request->input('end_time', '');
        // 查询
        $model = Car::query()
            ->where('id', $id)
            ->firstOrFail();

        // 分类查询
        $categories = new Collection();
        if (!empty($model->car_category_ids)) {
            $categories = CarCategory::query()
                ->whereIn('id', array_unique($model->car_category_ids))
                ->pluck('icon', 'id')
                ->filter();
        }
        $model_arr = $model->toArray();
        $price = $this->getCarPrice($model_arr);
        $model->price = $price;
        $model->price_calendar = [];
        $model->average_price = $price;
        if(!empty($start_time) && !empty($end_time)){
            $model->price_calendar = $this->getCarPriceCalendar($model_arr, strtotime($start_time), strtotime($end_time));
            $subtotal = "0";
            foreach ($model->price_calendar as $v){
                $subtotal = bcadd($subtotal, (string)$v);
            }
            $model->average_price = bcdiv($subtotal, (string)count($model->price_calendar), 0);
        }
        // 组装数据
        $model->icon = $this->getCategoryIcon($model, $categories);
        $model->setVisible(['banner', 'name', 'icon', 'base_config', 'high_light_config', 'price', 'price_calendar', 'average_price']);

        return $model;
    }

    /**
     * 获取某一天该车辆的价格
     * @param array $carModel
     * @param string|int $time
     * @return mixed
     */
    public function getCarPrice(Array $carModel,string|int $time = ""){
        if(empty($time) || intval($time) == 0){
            return $carModel['price'];
        }
        $time = $time ? $time : time();
        $price = $carModel['price'];
        if(!empty($carModel['special_prices'])){
            foreach ($carModel['special_prices'] as $v){
                if($time >= strtotime($v['date'][0].' 00:00:00') && $time <= strtotime($v['date'][1].' 23:59:59')){
                    $price = $v['price'];
                }
            }
        }
        return $price;
    }

    /**
     * 获取车辆价格日历
     * @return void
     */
    public function getCarPriceCalendar(Array $carModel,int $start_time,int $end_time){
        $price_calendar = [];
        $day_time = 60*60*24;
        $day_len = bcdiv(bcsub((string)$end_time, (string)$start_time), (string)$day_time);
        if(($end_time - $start_time)%$day_time > 0) $day_len = bcadd($day_len, '1');
        for ($i = 0; $i < $day_len; $i++){
            $time = bcadd((string)$start_time, bcmul((string)$day_time, (string)$i));
            $date = date('m-d', intval($time));
            $price_calendar[$date] = $this->getCarPrice($carModel, $time);
        }
        return $price_calendar;
    }

    /**
     * 获取分类icon
     * @param Car $model
     * @param Collection $categories
     * @return string
     */
    private function getCategoryIcon(Car $model, Collection $categories): string
    {
        $icon = '';

        if ($categories->isEmpty()) {
            return $icon;
        }

        foreach ($model->car_category_ids as $carCategoryId) {
            if (!empty($categories[$carCategoryId])) {
                $icon = $categories[$carCategoryId];
                break;
            }
        }

        return $icon;
    }
}
